home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
machserver
/
1.098
/
mach
/
sun4c.md
/
fpu_simulator.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-08-17
|
6KB
|
239 lines
#ifdef sccsid
static char sccsid[] = "@(#)fpu_simulator.c 1.8 88/02/08 SMI";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/* Main procedures for Sparc FPU simulator. */
/*
* This whole file refuses to lint.
*/
#ifndef lint
#include <sun4/fpu/fpu_simulator.h>
#include <sun4/fpu/globals.h>
#include <sys/signal.h>
/* PUBLIC FUNCTIONS */
PRIVATE enum ftt_type
_fp_fpu_simulator(inst, pfsr)
fp_inst_type inst; /* FPU instruction to simulate. */
fsr_type *pfsr; /* Pointer to image of FSR to read and write. */
{
unpacked us1, us2, ud; /* Unpacked operands and result. */
unsigned nrs1, nrs2, nrd; /* Register number fields. */
fsr_type fsr;
unsigned usr;
unsigned andexcep;
nrs1 = inst.rs1;
nrs2 = inst.rs2;
nrd = inst.rd;
_fp_current_exceptions = 0; /* Initialize current exceptions. */
fsr = *pfsr;
fp_direction = fsr.rd; /* Obtain rounding direction. */
fp_precision = fsr.rp; /* Obtain rounding direction. */
switch (inst.opcode) {
case fmovs:
_fp_unpack_word(&usr, nrs2);
_fp_pack_word(&usr, nrd);
break;
case fabss:
_fp_unpack_word(&usr, nrs2);
usr &= 0x7fffffff;
_fp_pack_word(&usr, nrd);
break;
case fnegs:
_fp_unpack_word(&usr, nrs2);
usr ^= 0x80000000;
_fp_pack_word(&usr, nrd);
break;
case fadd:
_fp_unpack(&us1, nrs1, inst.prec);
_fp_unpack(&us2, nrs2, inst.prec);
_fp_add(&us1, &us2, &ud);
_fp_pack(&ud, nrd, inst.prec);
break;
case fsub:
_fp_unpack(&us1, nrs1, inst.prec);
_fp_unpack(&us2, nrs2, inst.prec);
_fp_sub(&us1, &us2, &ud);
_fp_pack(&ud, nrd, inst.prec);
break;
case fmul:
_fp_unpack(&us1, nrs1, inst.prec);
_fp_unpack(&us2, nrs2, inst.prec);
_fp_mul(&us1, &us2, &ud);
_fp_pack(&ud, nrd, inst.prec);
break;
case fdiv:
_fp_unpack(&us1, nrs1, inst.prec);
_fp_unpack(&us2, nrs2, inst.prec);
_fp_div(&us1, &us2, &ud);
_fp_pack(&ud, nrd, inst.prec);
break;
case fcmp:
_fp_unpack(&us1, nrs1, inst.prec);
_fp_unpack(&us2, nrs2, inst.prec);
fsr.fcc = _fp_compare(&us1, &us2, 0);
break;
case fcmpe:
_fp_unpack(&us1, nrs1, inst.prec);
_fp_unpack(&us2, nrs2, inst.prec);
fsr.fcc = _fp_compare(&us1, &us2, 1);
break;
case fsqrt:
_fp_unpack(&us1, nrs2, inst.prec);
_fp_sqrt(&us1, &ud);
_fp_pack(&ud, nrd, inst.prec);
break;
case ftoi:
_fp_unpack(&us1, nrs2, inst.prec);
fp_direction = fp_tozero;
/* Force rounding toward zero. */
_fp_pack(&us1, nrd, fp_op_integer);
break;
case ftos:
_fp_unpack(&us1, nrs2, inst.prec);
_fp_pack(&us1, nrd, fp_op_single);
break;
case ftod:
_fp_unpack(&us1, nrs2, inst.prec);
_fp_pack(&us1, nrd, fp_op_double);
break;
case ftox:
_fp_unpack(&us1, nrs2, inst.prec);
_fp_pack(&us1, nrd, fp_op_extended);
break;
default:
return (ftt_unimplemented);
}
fsr.cexc = _fp_current_exceptions;
if (_fp_current_exceptions) { /* One or more exceptions occurred. */
andexcep = _fp_current_exceptions & fsr.tem;
if (andexcep != 0) { /* Signal an IEEE SIGFPE here. */
if (andexcep & (1 << fp_invalid))
fptrapcode = FPE_FLTOPERR_TRAP;
else if (andexcep & (1 << fp_overflow))
fptrapcode = FPE_FLTOVF_TRAP;
else if (andexcep & (1 << fp_underflow))
fptrapcode = FPE_FLTUND_TRAP;
else if (andexcep & (1 << fp_division))
fptrapcode = FPE_FLTDIV_TRAP;
else if (andexcep & (1 << fp_inexact))
fptrapcode = FPE_FLTINEX_TRAP;
else
fptrapcode = 0;
*pfsr = fsr;
return (ftt_ieee);
} else { /* Just set accrued exception field. */
fsr.aexc |= _fp_current_exceptions;
}
}
*pfsr = fsr;
return (ftt_none);
}
enum ftt_type
fpu_simulator(pinst, pfsr)
fp_inst_type *pinst; /* Pointer to FPU instruction to simulate. */
fsr_type *pfsr; /* Pointer to image of FSR to read and write. */
/*
* fpu_simulator simulates FPU instructions only; reads and writes FPU data
* registers directly.
*/
{
union {
int i;
fp_inst_type inst;
} kluge;
enum ftt_type ftt;
fptrapaddr = (char *) pinst; /* bad inst addr in case we trap */
_fp_current_read_freg = _fp_read_pfreg;
_fp_current_write_freg = _fp_write_pfreg;
ftt = _fp_read_word((caddr_t) pinst, &(kluge.i));
if (ftt != ftt_none)
return (ftt);
return _fp_fpu_simulator(kluge.inst, pfsr);
}
enum ftt_type
fp_emulator(pinst, pregs, pwindow, pfpu)
fp_inst_type *pinst; /* Pointer to FPU instruction to simulate. */
struct regs *pregs; /* Pointer to PCB image of registers. */
struct rwindow *pwindow;/* Pointer to locals and ins. */
struct fpu *pfpu; /* Pointer to FPU register block. */
/*
* fp_emulator simulates FPU and CPU-FPU instructions; reads and writes FPU
* data registers from image in pfpu.
*/
{
union {
int i;
fp_inst_type inst;
} kluge;
enum ftt_type ftt;
fptrapaddr = (char *) pinst; /* bad inst addr in case we trap */
_fp_current_pfregs = pfpu;
_fp_current_read_freg = _fp_read_vfreg;
_fp_current_write_freg = _fp_write_vfreg;
ftt = _fp_read_word((caddr_t) pinst, &(kluge.i));
if (ftt != ftt_none)
return (ftt);
if ((kluge.inst.hibits == 2) && ((kluge.inst.op3 == 0x34) || (kluge.inst.op3 == 0x35))) {
pregs->r_pc = pregs->r_npc; /* Do not retry emulated
* instruction. */
pregs->r_npc += 4;
return _fp_fpu_simulator(kluge.inst, (fsr_type *) & (pfpu->fpu_fsr));
} else
return _fp_iu_simulator(kluge.inst, pregs, pwindow, pfpu);
}
#ifndef sprite
#include <sys/param.h>
#include <sys/user.h>
#include <sun4/trap.h>
/*
* Handle traps for UNIX.
*/
void
fp_traps(ftt, rp)
register enum ftt_type ftt; /* trap type */
register struct regs *rp; /* ptr to regs fro trap */
{
extern void trap();
switch(ftt) {
case ftt_ieee:
u.u_code = fptrapcode;
trap(T_FP_EXCEPTION, rp, fptrapaddr, 0, 0);
break;
case ftt_fault:
trap(T_DATA_FAULT, rp, fptrapaddr, 0, fptraprw);
break;
case ftt_alignment:
trap(T_ALIGNMENT, rp, fptrapaddr, 0, 0);
break;
case ftt_unimplemented:
trap(T_UNIMP_INSTR, rp, fptrapaddr, 0, 0);
break;
default:
/*
* We don't expect any of the other types here.
*/
panic("fp_traps: bad ftt");
}
}
#endif
#endif /* lint */